package com.zhijian.medical.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.format.FastDateFormat;
import cn.hutool.core.util.RandomUtil;
import com.lowagie.text.DocumentException;
import com.zhijian.medical.config.CommonConfig;
import com.zhijian.medical.dao.local.NewFileMapper;
import com.zhijian.medical.entity.UploadParam;
import com.zhijian.medical.entity.dto.PersonDto;
import com.zhijian.medical.entity.po.NewFile;
import com.zhijian.medical.entity.po.NewFileHistory;
import com.zhijian.medical.entity.vo.request.DeviceSearchVo;
import com.zhijian.medical.entity.vo.request.NewFileSearchVo;
import com.zhijian.medical.entity.vo.request.NewFileUpdateVo;
import com.zhijian.medical.entity.vo.response.DeviceVo;
import com.zhijian.medical.entity.vo.response.NewFileVo;
import com.zhijian.medical.enums.NewFileTypeEnum;
import com.zhijian.medical.enums.ResponseCodeEnum;
import com.zhijian.medical.exception.BusinessException;
import com.zhijian.medical.holder.CurrentUserHolder;
import com.zhijian.medical.service.DeviceService;
import com.zhijian.medical.service.NewFileHistoryService;
import com.zhijian.medical.service.NewFileService;
import com.zhijian.medical.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 新文件管理业务处理层
 *
 * @author HCG
 * @version: 1.0
 * @date 2022-07-03 15:48:39
 */
@Slf4j
@Service
public class NewFileServiceImpl implements NewFileService {

    @Autowired
    private NewFileMapper mapper;

    @Autowired
    private NewFileHistoryService newFileHistoryService;

    @Autowired
    private CommonConfig commonConfig;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private UploadParam uploadParam;

    @Override
    public NewFile selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public NewFileVo selectVoById(Long id) {
        return mapper.selectVoById(id);
    }

    @Override
    public void deleteById(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public Long insert(NewFile newFile) {
        NewFileTypeEnum newFileTypeEnum = NewFileTypeEnum.getByCode(newFile.getType().intValue());
        AssertUtil.notNull(newFileTypeEnum, "类型非法");
        Date now = new Date();
        newFile.setCreateTime(now);
        newFile.setUpdateTime(now);
        if (StringUtils.isBlank(newFile.getNumber())) {
            newFile.setNumber(createNextNumberByTypeNew(newFile.getType()));
        }
        Long id = mapper.insert(newFile) > 0 ? newFile.getId() : 0L;
        if (newFile.getType() == NewFileTypeEnum.SBSMS.getCode().byteValue()) {
            //如果类型是设备品类说明书，就要同步到所属品类的设备中
            List<DeviceVo> deviceVos = deviceService.selectList(DeviceSearchVo.builder()
                    .categoryId(Long.valueOf(newFile.getExt1()))
                    .build());
            if (CollectionUtil.isNotEmpty(deviceVos)) {
                for (DeviceVo deviceVo : deviceVos) {
                    NewFile sbsms2 = new NewFile();
                    BeanUtils.copyProperties(newFile, sbsms2);
                    sbsms2.setExt1(deviceVo.getId() + "");
                    //设备详情说明书
                    sbsms2.setType(NewFileTypeEnum.SBSMS2.getCode());
                    mapper.insert(sbsms2);
                }
            }
        }
        return id;
    }

    @Override
    public boolean update(NewFile newFile) {
        Date now = new Date();
        newFile.setUpdateTime(now);
        return mapper.updateByPrimaryKey(newFile) != 0;
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    @Override
    public boolean update(NewFileUpdateVo newFileUpdateVo) {
        NewFile oldNewFile = this.selectById(newFileUpdateVo.getId());
        AssertUtil.notNull(oldNewFile, "此文件不存在或者已被删除");
        NewFile newFile = new NewFile();
        BeanUtils.copyProperties(newFileUpdateVo, newFile);
        this.update(newFile);
        NewFileHistory newFileHistory = new NewFileHistory();
        BeanUtils.copyProperties(newFileUpdateVo, newFileHistory);
        newFileHistory.setNewFileId(newFileUpdateVo.getId());
        return newFileHistoryService.insert(newFileHistory) != 0;
    }

    @Override
    public boolean updateByPrimaryKeySelective(NewFile record) {
        Date now = new Date();
        record.setUpdateTime(now);
        return mapper.updateByPrimaryKeySelective(record) != 0;
    }

    @Override
    public Integer count(NewFileSearchVo newFileSearchVo) {
        return mapper.count(newFileSearchVo);
    }

    @Override
    public List<NewFileVo> selectList(NewFileSearchVo newFileSearchVo) {
        return mapper.selectList(newFileSearchVo);
    }

    @Override
    public Page<NewFileVo> selectPage(NewFileSearchVo newFileSearchVo) {
        //先直接查总数
        int count = count(newFileSearchVo);
        //分页
        Page<NewFileVo> page = new Page<>(true, count, newFileSearchVo.getPageNum(), newFileSearchVo.getPageSize());
        newFileSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<NewFileVo> responseVos = this.selectList(newFileSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Override
    public String selectMaxNumberByType(Byte type) {
        return mapper.selectMaxNumberByType(type);
    }

    @Override
    public String createNextNumberByType(Byte type) {
        String maxNumberByType = this.selectMaxNumberByType(type);
        if (StringUtils.isBlank(maxNumberByType)) {
            return "0001";
        }
        Integer i = Integer.valueOf(maxNumberByType);
        int result = i + 1;
        String s = result + "";
        switch (s.length()) {
            case 1:
                return String.format("%04d", result);
            case 2:
                return String.format("%03d", result);
            case 3:
                return String.format("%02d", result);
            case 4:
                return s;
            case 5:
            default:
                throw new BusinessException(ResponseCodeEnum.FAILURE.code, "编号超过最大限制");
        }

    }

    @Override
    public boolean discard(Long id) {
        NewFile newFile = this.selectById(id);
        AssertUtil.notNull(newFile, "此文件不存在或者已被删除");

        NewFileTypeEnum newFileTypeEnum = NewFileTypeEnum.getByCode(newFile.getType().intValue());
        String typeStr = Objects.nonNull(newFileTypeEnum) ? newFileTypeEnum.getDesc() : null;

        PersonDto user = CurrentUserHolder.getUser();
        return this.updateByPrimaryKeySelective(NewFile.builder()
                .id(id)
                .type(NewFileTypeEnum.DISCARD.getCode())
                .discardTime(new Date())
                .typeStr(typeStr)
                //把废纸人存起来
                .ext3(user.getName())
                .ext4(user.getId() + "")
                .build());
    }

    @Override
    public NewFileVo selectNewestVoByType(Integer type) {
        return mapper.selectNewestVoByType(type);
    }

    @Override
    public void preview(Long id, HttpServletResponse resp) {
        NewFile newFile = this.selectById(id);
        if (Objects.isNull(newFile)) {
            return;
        }
        String filePath = newFile.getFilePath();
        if (StringUtils.isBlank(filePath)) {
            return;
        }
        this.preview(filePath, resp);
    }

    @Override
    public void preview(String filePath, HttpServletResponse resp) {
        String type = filePath.substring(filePath.lastIndexOf(".") + 1, filePath.length());
        //这里的2，是年份文件夹的开头
        String subFilePath = filePath.substring(filePath.indexOf("2"), filePath.length());
        switch (type) {
            case "doc":
                try {
                    DocPreviewUtil.outputHtml(DocPreviewUtil.convertDoc2Html(commonConfig.getStorePath() + subFilePath), resp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case "xls":
                try {
                    DocPreviewUtil.outputHtml(DocPreviewUtil.convertExcel2Html(commonConfig.getStorePath() + subFilePath, false), resp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case "xlsx":
                try {
                    DocPreviewUtil.outputHtml(DocPreviewUtil.convertExcel2Html(commonConfig.getStorePath() + subFilePath, true), resp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }

    @Override
    public boolean addWaterMark(Long id) {
        NewFile newFile = this.selectById(id);
        AssertUtil.notNull(newFile, "此文件不存在或者已被删除");
        //这里的2，是年份文件夹的开头
        String filePath = newFile.getFilePath();
        String subFilePath = filePath.substring(filePath.indexOf("2"), filePath.length());

        File oldFile = new File(commonConfig.getStorePath() + subFilePath);
        //格式
        String type = subFilePath.substring(subFilePath.lastIndexOf(".") + 1, subFilePath.length());
        //目前只支持PDF文件加水印
        AssertUtil.check(!"pdf".equalsIgnoreCase(type), "目前只支持PDF文件");

//            if (newFile.getDesc() == NewFileTypeEnum.SBSMS.getCode().byteValue()) {
//                //如果类型是设备说明书
//            }
        Date now = new Date();
        //水印的日期内容
        String s1 = DateUtil.format(now, FastDateFormat.getInstance("yyyy年MM月dd日"));

        String today = DateUtil.format(now, new SimpleDateFormat("yyyy/MM/dd"));
        //加过水印的新PDF文件名称
        String newFileName = String.format("%s.pdf", RandomUtil.randomString(10));
        //加过水印的新PDF路径
        String newFilePath = String.format("%s%s%s%s%s", uploadParam.getStorePath(), File.separator, today, File.separator, newFileName);
        File dest = new File(newFilePath);

        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        try {
            WaterMarkUtil.setWatermark(oldFile.getAbsolutePath(), dest.getAbsolutePath(), "受控文件", String.format("生效日期：%s", s1), "");
        } catch (DocumentException | IllegalAccessException | IOException | NoSuchFieldException e) {
            e.printStackTrace();
            return false;
        }


        return this.updateByPrimaryKeySelective(NewFile.builder()
                .id(id)
                .filePath(String.format("%s%s%s%s", uploadParam.getUrlPath(), today, File.separator, newFileName))
                .ext1("true")
                .build());
    }

    /**
     * 根据类型获取最新的编号
     *
     * @param type
     * @return
     */
    private String createNextNumberByTypeNew(Integer type) {
        NewFileTypeEnum newFileTypeEnum = NewFileTypeEnum.getByCode(type.intValue());
        AssertUtil.notNull(newFileTypeEnum, "类型非法");
        assert newFileTypeEnum != null;
        //最终的数字
        String finalNumber = "0001";
        NewFileVo newFileVo = this.selectNewestVoByType(type);
        if (Objects.isNull(newFileVo)) {
            return String.format(newFileTypeEnum.getNumber(), finalNumber);
        }
        //编号
        String number = newFileVo.getNumber();
        if (StringUtils.isBlank(number)) {
            return String.format(newFileTypeEnum.getNumber(), finalNumber);
        }

        Integer i = StrUtil.drawNumberFromStr(number);
        int result = i + 1;
        String s = result + "";
        switch (s.length()) {
            case 1:
                finalNumber = String.format("%04d", result);
                break;
            case 2:
                finalNumber = String.format("%03d", result);
                break;
            case 3:
                finalNumber = String.format("%02d", result);
                break;
            case 4:
                finalNumber = s;
                break;
            case 5:
                throw new BusinessException(ResponseCodeEnum.FAILURE.code, "编号超过最大限制");
            default:
                throw new BusinessException(ResponseCodeEnum.FAILURE.code, "编号超过最大限制");
        }
        return String.format(newFileTypeEnum.getNumber(), finalNumber);
//        switch (newFileTypeEnum) {
//            case FLBZ:
//            case ZLSC:
//            case CXWJ:
//            case SOP:
//            case JLBD:
//            case SYSAQSC:
//            case ZNGS:
//            case DZSJ:
//            case SJSMS:
//            case SBSMS:
//                return String.format("BLK-%s-%s", CnToSpellUtil.getFirstUp(newFileTypeEnum.getDesc()), finalNumber);
//            default:
//                return finalNumber;
    }


}